package com.benew.ntt.evaluate.sdk

import android.content.Context
import android.os.Looper
import com.benew.ntt.evaluate.EvalScore
import com.benew.ntt.evaluate.constant.EvalConst
import com.benew.ntt.evaluate.constant.EvalError
import com.benew.ntt.evaluate.constant.EvalStatus
import com.benew.ntt.evaluate.listener.IEvalSDK
import com.benew.ntt.evaluate.utils.EvalFileUtils
import com.blankj.utilcode.util.GsonUtils
import com.blankj.utilcode.util.NetworkUtils
import com.blankj.utilcode.util.StringUtils
import com.blankj.utilcode.util.ToastUtils
import com.ntt.core.nlogger.NLogger
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.net.URISyntaxException

/**
 * 口语评测管理器
 */
object EvalSDK {
    private val TAG = javaClass.simpleName

    private var mEntity: EvalSDKEntity? = null
    private var mEvalListeners = mutableSetOf<IEvalSDKListener>()
    private var mEvalSDK: IEvalSDK? = null
    private var mEvalStatus = EvalStatus.UNKNOW

    fun init(context: Context, config: EvalSDKConfig? = null) {
        try {
            EvalConst.config = config
            val className = if (config?.getPlatform() == EvalSDKPlatform.XS) {
                "com.benew.ntt.xseval.sdk.XSEvalSDK"
            } else {
                "com.benew.ntt.ydeval.sdk.YDEvalSDK"
            }
            val aClass = Class.forName(className)
            mEvalSDK = aClass.newInstance() as IEvalSDK
        } catch (e: Exception) {
            NLogger.e(TAG, "反射失败：", e.message)
            e.printStackTrace()
        }
        mEvalSDK?.init(context, mEvalListeners, mEvalSDKHandler)
        EvalScore.setLevelConfig()
        EvalFileUtils.deleteFilesNDaysAgo()
    }

    fun getCurrEntity(): EvalSDKEntity? {
        return mEntity
    }

    /**
     * 获取配置
     */
    fun getConfig(): EvalSDKConfig? {
        return EvalConst.config
    }

    /**
     * 在调用开始录音前需要先实现 IEvaluationListener 接口
     *
     * @param entity 需要评测的内容
     */
    fun startEval(entity: EvalSDKEntity?) {
        if (mEvalSDK == null) {
            NLogger.e(TAG, "评测初始化失败")
            mEvalListeners.map { listener ->
                listener.onError("未初始化！", EvalError.ERROR_1)
            }
            return
        }

        //替换‘不间断空格符’为正常空格符，去除首尾空格
        entity?.content = entity?.content?.replace("\\u00A0".toRegex(), " ")?.trim()
        if (
            entity == null
            || StringUtils.isEmpty(entity.content)
            || StringUtils.isEmpty(entity.type)
        ) {
            NLogger.e(
                TAG, "请检查评测的内容或者类型是否正常！",
                entity == null,
                entity?.content,
                entity?.type
            )
            ToastUtils.showShort("请检查评测的内容或者类型是否正常！")
            return
        }
        cancelEval()
        mEntity = entity
        NLogger.e(TAG, "startEval 开启评测", GsonUtils.toJson(entity))
        mEvalSDKHandler.sendStartEval(entity)
        try {
            mEvalSDK?.startEval(entity)
        } catch (e: URISyntaxException) {
            e.printStackTrace()
            NLogger.e(TAG, "startEval 开启评测异常", e.message)
            mEvalSDKHandler.sendError("开启评测异常，请稍后再试！", EvalError.ERROR_2)
        }
    }


    /**
     * 停止录音
     */
    fun stopRecord() {
        NLogger.e(TAG, "stopRecord 停止录音")
        mEvalSDK?.stopRecord()
    }

    /**
     * 取消评测
     */
    fun cancelEval() {
        NLogger.e(TAG, "cancelEval 取消评测")
        mEvalSDK?.cancelEval()
        mEvalSDKHandler.sendCancel()
    }

    /**
     * 删除评测引擎
     */
    fun deleteEval() {
        NLogger.e(TAG, "cancelEval 删除评测引擎")
        mEvalSDK?.deleteEval()
    }

    /**
     * 注册监听器
     */
    fun registerEvalListener(evalListener: IEvalSDKListener) {
        NLogger.e(TAG, "registerEvalListener 注册监听器", mEvalListeners.size)
        mEvalListeners.add(evalListener)
    }

    /**
     * 注销监听器
     */
    fun unRegisterEvalListener(evalListener: IEvalSDKListener) {
        NLogger.e(TAG, "unRegisterEvalListener 注销监听器", mEvalListeners.size)
        mEvalListeners.remove(evalListener)
    }

    private val mEvalSDKHandler = EvalSDKHandler(Looper.getMainLooper()) { msg ->
        when (msg.what) {
            EvalSDKWhat.START_EVAL -> {
                mEvalStatus = EvalStatus.CONNECTING
                NLogger.d(TAG, "EvalHandler 启动评测,在连接中")
                mEvalListeners.map { listener ->
                    listener.onStartEval(msg.obj as EvalSDKEntity)
                }
            }
            EvalSDKWhat.ERROR -> {
                if (mEvalStatus != EvalStatus.SHOW_SCORE) {
                    mEvalStatus = EvalStatus.ERROR
                    val errorMsg = msg.obj as String? ?: "评测异常，请尝试重新评测哦！"
                    mEvalListeners.map { listener ->
                        listener.onError(errorMsg, msg.arg1)
                    }
                } else {
                    NLogger.d(TAG, "EvalHandler 评测异常,但是分数出来了")
                }
            }
            EvalSDKWhat.START_RECORD -> {
                mEvalStatus = EvalStatus.RECORDING
                NLogger.d(TAG, "EvalHandler 评测开始录音")
                mEvalListeners.map { listener ->
                    listener.onStartRecord()
                }
            }
            EvalSDKWhat.RECORDING -> {
                val array = msg.obj as Array<*>
                NLogger.d(TAG, "EvalHandler 录音分贝${array[3]}")
                mEvalListeners.map { listener ->
                    listener.recordOfByte(
                        array[0] as ByteArray,
                        array[1] as Int,
                        array[2] as Int,
                        array[3] as Double
                    )
                }
            }
            EvalSDKWhat.PROGRESS -> {
                NLogger.d(TAG, "EvalHandler 评测中")
                mEvalStatus = EvalStatus.RECORDING
                mEvalListeners.map { listener ->
                    listener.onProgress(msg.obj as String?)
                }
            }
            EvalSDKWhat.RECORD_END -> {
                NLogger.d(TAG, "EvalHandler 评测录音结束")
            }
            EvalSDKWhat.RECORD_TIMEOUT -> {
                stopRecord()
                NLogger.d(TAG, "EvalHandler 评测录音结束")
            }
            EvalSDKWhat.RESULT -> {
                mEvalStatus = EvalStatus.SHOW_SCORE
                NLogger.d(TAG, "EvalHandler 评测显示分数")
                val obj = msg.obj as String?
                mEvalListeners.map { listener ->
                    listener.onEvalResult(obj, mEntity)
                }
            }
            EvalSDKWhat.EVAL_CLOSE -> {
                //有可能没走到评分结果那一步就关闭了连接,所以该结果为空
                if (mEvalStatus == EvalStatus.RECORDING) {
                    mEvalStatus = EvalStatus.SHOW_SCORE
                    NLogger.d(TAG, "EvalHandler socket关闭，评测显示分数")
                    mEvalListeners.map { listener ->
                        listener.onEvalResult("", mEntity)
                    }
                }
            }
            EvalSDKWhat.RECORD_FILE -> {
                val recordPath = msg.obj as String?
                mEvalListeners.map { listener ->
                    listener.onRecordFile(recordPath)
                }
            }
            EvalSDKWhat.TIMEOUT -> {
                if (mEvalStatus != EvalStatus.SHOW_SCORE) {
                    mEvalStatus = EvalStatus.ERROR
                    NLogger.d(TAG, "EvalHandler 评测超时")
                    mEvalSDK?.cancelEval()
                    mEvalListeners.map { listener ->
                        listener.onTimeOut()
                    }
                } else {
                    NLogger.d(TAG, "EvalHandler 评测异常,但是分数出来了")
                }
            }
            EvalSDKWhat.CANCEL -> {
                mEvalListeners.map { listener ->
                    listener.onCancel()
                }
            }
        }
        true
    }

}